package com.skyjing.askit

import android.content.Context
import androidx.annotation.IntDef
import androidx.collection.SimpleArrayMap
import com.skyjing.askit.AsTool.getApp
import java.lang.annotation.Retention
import java.lang.annotation.RetentionPolicy

/**
 * 内置文件存储操作类
 */
object AsAppFile {
    private val FILE_UTILS_MAP = SimpleArrayMap<String, AppFile>()
    @JvmStatic
    fun init() {
        init(
            spName = AsTool.getPageName().toString(),
            mode = Context.MODE_PRIVATE
        )
    }

    @JvmStatic
    fun init(mode: Int = Context.MODE_PRIVATE) {
        init(
            spName = AsTool.getPageName().toString(),
            mode = Context.MODE_PRIVATE
        )
    }

    @JvmStatic
    fun init(spName: String = AsTool.getPageName().toString()) {
        init(spName, mode = Context.MODE_PRIVATE)
    }

    @JvmStatic
    fun init(spName: String = AsTool.getPageName().toString(), mode: Int = Context.MODE_PRIVATE) {
        var spName = spName
        if (isEmpty(spName)) spName = AsTool.getPageName().toString()
        var spUtils = FILE_UTILS_MAP[spName]
        if (spUtils == null) {
            FILE_UTILS_MAP.put(spName,
                AppFile(spName, mode)
            )
        }
    }

    @JvmStatic
    fun read():String? {
        return read(AsTool.getPageName().toString())
    }

    @JvmStatic
    fun read(tag : String = AsTool.getPageName().toString()):String? {
        return FILE_UTILS_MAP[tag]?.read()
    }

    @JvmStatic
    fun write(msg: String) {
        return write(
            AsTool.getPageName().toString(),
            msg
        )
    }

    @JvmStatic
    fun write(tag : String = AsTool.getPageName().toString(), msg: String) {
        FILE_UTILS_MAP[tag]?.write(msg)
    }

    @JvmStatic
    fun write(msg: Int) {
        return write(
            AsTool.getPageName().toString(),
            msg
        )
    }

    @JvmStatic
    fun write(tag : String = AsTool.getPageName().toString(), msg: Int) {
        FILE_UTILS_MAP[tag]?.write(msg)
    }

    @JvmStatic
    fun write(msg: ByteArray) {
        return write(
            AsTool.getPageName().toString(),
            msg
        )
    }

    @JvmStatic
    fun write(tag : String = AsTool.getPageName().toString(), msg: ByteArray) {
        FILE_UTILS_MAP[tag]?.write(msg)
    }



    private fun isEmpty(s: String?): Boolean {
        if (s == null) return true
        var i = 0
        val len = s.length
        while (i < len) {
            if (!Character.isWhitespace(s[i])) {
                return false
            }
            ++i
        }
        return true
    }

    private class AppFile {
        private var fileName: String = AsTool.getPageName().toString()
        private var mode: Int = Context.MODE_PRIVATE
        constructor(name: String) {
            fileName = name
            mode = Context.MODE_PRIVATE
        }

        constructor(name: String, @AppFileAble.mode mode: Int) {
            fileName = name
            this.mode = mode
        }

        fun read(): String? {
            try {
                val inStream = getApp()!!.openFileInput(fileName)
                val buffer = ByteArray(1024)
                var hasRead = 0
                val sb = StringBuilder()
                while (inStream.read(buffer).also { hasRead = it } != -1) {
                    sb.append(String(buffer, 0, hasRead))
                }
                inStream.close()
                return sb.toString()
            } catch (e: Exception) {
                e.printStackTrace()
            }
            return null
        }

        fun write(msg: String?) { // 步骤1：获取输入值
            if (msg == null) return
            try { // 步骤2:创建一个FileOutputStream对象,MODE_APPEND追加模式
                val fos =
                    getApp()!!.openFileOutput(fileName, mode)
                // 步骤3：将获取过来的值放入文件
                fos.write(msg.toByteArray())
                // 步骤4：关闭数据流
                fos.close()
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

        fun write(msg: Int) {
            try {
                val fos =
                    getApp()!!.openFileOutput(fileName, mode)
                fos.write(msg)
                fos.close()
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

        fun write(msg: ByteArray?) {
            if (msg == null) return
            try {
                val fos =
                    getApp()!!.openFileOutput(fileName, mode)
                fos.write(msg)
                fos.close()
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

        fun write(msg: ByteArray?, off: Int, len: Int) {
            if (msg == null) return
            try {
                val fos =
                    getApp()!!.openFileOutput(fileName, mode)
                fos.write(msg, off, len)
                fos.close()
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

        interface AppFileAble {
            @Retention(RetentionPolicy.SOURCE)
            @IntDef(
                PRIVATE,
                APPEND,
                READABLE,
                WRITEABLE
            )
            annotation class mode

            companion object {
                const val PRIVATE = Context.MODE_PRIVATE
                const val APPEND = Context.MODE_APPEND
                const val READABLE = Context.MODE_WORLD_READABLE
                const val WRITEABLE = Context.MODE_WORLD_WRITEABLE
            }
        }

        companion object {
            private val INTERNAL_FILE =
                SimpleArrayMap<String, AsAppFile>()

            /**
             * Context.MODE_PRIVATE：为默认操作模式，代表该文件是私有数据，只能被应用本身访问，
             * 在该模式下，写入的内容会覆盖原文件的内容，如果想把新写入的内容追加到原文件中。可以使用Context.MODE_APPEND
             * Context.MODE_APPEND：模式会检查文件是否存在，存在就往文件追加内容，
             * 否则就创建新文件。
             * Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE用来控制其他应用是否有权限读写该文件。
             * MODE_WORLD_READABLE：表示当前文件可以被其他应用读取；
             * MODE_WORLD_WRITEABLE：表示当前文件可以被其他应用写入。
             *
             * @return
             */
//    public static AppFile getInstance() {
//        return getInstance("", Context.MODE_PRIVATE);
//    }
//    public static AppFile getInstance(int mode) {
//        return getInstance("", mode);
//    }
//            @SuppressLint("WrongConstant")
//            fun getInstance(name: String): AsAppFile2 {
//                return getInstance(name, Context.MODE_PRIVATE)
//            }

//            fun getInstance(name: String, @AppFileAble.mode mode: Int): AsAppFile2 {
//                var name = name
//                if (isEmpty(name)) name = "AppFile"
//                var appFile = INTERNAL_FILE[name]
//                if (appFile == null) {
//                    appFile = AsAppFile2(name, mode)
//                    INTERNAL_FILE.put(name, appFile)
//                }
//                return appFile
//            }
        }
    }
}